package com.xxxx.comment.utils;

import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Component
public class RedisIdWorker
{
    /**
     * 开始时间戳,从1970.01.01 00:00:00 开始 到2022.01.01 00:00:00 的 秒数，即1640995200秒
     */
    private static final long BEGIN_TIMESTAMP = 1640995200L;

    /**
     * 序列号的位数
     */
    private static final int COUNT_BITS = 32;

    private final StringRedisTemplate stringRedisTemplate;

    public RedisIdWorker(StringRedisTemplate stringRedisTemplate)
    {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    /**
     * 根据传入的业务名生成下一个订单ID
     * @param businessName 业务名，不要带冒号
     * @return
     */
    public long nextId(String businessName)
    {
        // 1.生成时间戳，足够用到2106年，减什么BEGIN_TIMESTAMP，多余！！！
        LocalDateTime now = LocalDateTime.now();
        long nowSecond = now.toEpochSecond(ZoneOffset.UTC);
        long timestamp = nowSecond - BEGIN_TIMESTAMP;

        // 2.生成序列号
        // 2.1.获取当前日期，精确到天
        String date = now.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
        // 2.2.自增长
        Long count = stringRedisTemplate.opsForValue()
                .increment("icr:" + businessName + ":" + date);
        // 3.拼接并返回
        Assert.notNull(count, "订单ID生成错误，请联系管理员！");

        String id = date.replace("/", "")
                + String.valueOf(timestamp << COUNT_BITS | count).substring(8);
        return Long.parseLong(id);
    }

   public static void main(String[] args) throws InterruptedException
   {
       // 创建redis配置
       RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration();
       redisConfig.setHostName("127.0.0.1");  // Redis 主机名
       redisConfig.setPort(6379);  // Redis 端口号

       // 创建 LettuceConnectionFactory
       LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(redisConfig);
       connectionFactory.afterPropertiesSet();  // 初始化连接工厂

       // 创建 StringRedisTemplate
       StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
       stringRedisTemplate.setConnectionFactory(connectionFactory);
       stringRedisTemplate.afterPropertiesSet();  // 初始化 StringRedisTemplate

       // 生成ID，同时使用countDownLatch确保多线程环境下只生成3个ID
       RedisIdWorker redisIdWorker = new RedisIdWorker(stringRedisTemplate);
       CountDownLatch countDownLatch = new CountDownLatch(3);

       Runnable task = () -> {
           for (int i = 0; i < 10; i++)
           {
               long id = redisIdWorker.nextId("order");
               System.out.println("id = " + id);
           }
           countDownLatch.countDown();
           System.out.println(countDownLatch.getCount());
       };
       ExecutorService executorService = Executors.newFixedThreadPool(10);
       long begin = System.currentTimeMillis();
       for (int i = 0; i < 10; i++)
           executorService.execute(task);
       countDownLatch.await();
       System.out.println("work!!!");
       long end = System.currentTimeMillis();
       System.out.println("time = " + -(begin - end));
   }
}
